import numpy as np  
from scipy.optimize import basinhopping  
import matplotlib.pyplot as plt  
import os  
  
# 使用之前定义的calculate_cost函数  
def calculate_cost(x, parameters):  
    x1, x2, x3, xf, xd = x  
    p1, p2, p3, C_assemble, C_finished, C_dismantle, C_exchange, Ct1, Ct2, Ct3, n1, n2, n3, n_finished = parameters  
      
    # 零配件检测成本  
    cost_parts = x1 * Ct1 * n1 + x2 * Ct2 * n2 + x3 * Ct3 * n3  
    # 装配成本  
    cost_assemble = C_assemble * n_finished  
    # 产品检测成本  
    cost_product = xf * C_finished * n_finished  
    # 成品次品率计算  
    if p3 != 0:  
        p_assembly = (1 - x1) * p1 + (1 - x2) * p2 + (1 - x3) * p3 - (1 - x1) * (1 - x2) * (1 - x3) * p1 * p2 * p3  
    else:  
        p_assembly = (1 - x1) * p1 + (1 - x2) * p2 - (1 - x1) * (1 - x2) * p1 * p2  
    pf = 1 - (1 - p_assembly) ** 2  
    # 拆解和调换成本  
    cost_rework = xd * C_dismantle * pf * n_finished  
    if C_exchange != 0:  
        cost_replace = (1 - xd) * C_exchange * pf * n_finished  
    else:  
        cost_replace = 0  
    # 总成本  
    total_cost = cost_parts + cost_assemble + cost_product + cost_rework + cost_replace  
    return total_cost  
  
# 封装盆地跳跃优化函数  
def optimize_cost_basinhopping(parameters, count):  
    # 定义初始猜测  
    initial_guess = [0, 0, 0, 0, 0]  
      
    # 定义边界 [0, 1] 对于所有变量  
    bounds = [(0, 1), (0, 1), (0, 1), (0, 1), (0, 1)]  
      
    # 创建一个列表来存储每次迭代的成本  
    cost_history = []  
      
    # 定义一个回调函数，用于在每次迭代后记录成本  
    def callback(x, f, accepted):  
        cost_history.append(f)  
      
    # 使用 basinhopping 进行优化  
    result = basinhopping(lambda x: calculate_cost(x, parameters),  
                         initial_guess, niter=500, T=2.0, stepsize=0.5,  
                         minimizer_kwargs={"bounds": bounds},  
                         callback=callback)  
      
    # 输出最优解  
    best_individual = [int(i) for i in result.x]  
    best_cost = result.fun  
    print(f"Best Individual: {best_individual} (x1, x2, x3, xf, xd)")  
    print(f"Minimum Cost: {best_cost}")  
      
    # 绘制迭代图  
    plt.figure(figsize=(10, 6))  
    plt.plot(cost_history)  
    plt.ylabel('Cost')  
    plt.xlabel('Iteration')  
    plt.title('Cost vs. Iteration')  
    plt.grid(True)  
      
    # 确保输出文件夹存在  
    output_dir = 'test3_anneal_picture'  
    if not os.path.exists(output_dir):  
        os.makedirs(output_dir)  
      
    # 保存图片到指定文件夹  
    plt.savefig(os.path.join(output_dir, f'cost_vs_iteration{count}.png'))  
    plt.close()  
  
# 参数列表  
parameters_list = [  
    (0.1, 0.1, 0.1, 8, 4, 6, 0, 1, 1, 2, 100, 100, 100, 90),  
    (0.1, 0.1, 0.1, 8, 4, 6, 0, 1, 1, 2, 100, 100, 100, 90),  
    (0.1, 0.1, 0, 8, 4, 6, 0, 1, 2, 0, 100, 100, 0, 90),  
    (0.1, 0.1, 0.1, 8, 6, 10, 40, 4, 4, 4, 90, 90, 90, 81)  
]  
  
# 调用优化函数  
for index, parameters in enumerate(parameters_list, start=1):  
    optimize_cost_basinhopping(parameters, index)